<!--
 * @Author: ZJoker
 * @Date: 2023-02-15 13:59:52
 * @LastEditTime: 2023-12-20 16:46:20
 * @LastEditors: ZJoker
 * @Description: ECharts组件, 包含容器div、ECharts实例化功能。
 *               容器支持设置宽(width: string | number)高(height: string | number)
 *               支持注册地图(需要传入mapName, geoJson)
 *               支持注册第三方数据转换器(需要传入transform: ExternalDataTransform)
 *               支持实例化后的自定义事件instantiated(echartsInstance): void, 可在此阶段添加ECharts的事件处理函数.
 * @FilePath: \jzsy-radio-receiver-client\src\components\echart\Index.vue
 * 生活百般滋味，人生需要笑对
-->
<template>
  <div
    ref="chartContainerRefs"
    class="chartContainer"
    :style="{ width: containerWidth, height: containerHeight }"
  ></div>
</template>

<script setup>
import * as echarts from 'echarts'
import { ref, computed, watch, onMounted } from 'vue'

const props = defineProps({
  /** 图表高度 */
  height: {
    type: [Number, String],
    default: '100%'
  },
  /** 图表宽度 */
  width: {
    type: [Number, String],
    default: '100%'
  },
  /** EChart配置项 */
  options: {
    type: Object,
    required: true
  },
  /** 地图geoJson */
  geoJson: {
    type: Object
  },
  /** 地图名称，在 geo 组件或者 map 图表类型中设置的 map 对应的就是该值。 */
  mapName: {
    type: String
  },
  /** 外部数据转换器对象, 如: ecStat.transform.clustering */
  transform: {
    type: Object
  },
  wordCloud: {
    type: Boolean,
    default: false
  },
  notMerge: {
    type: Boolean,
    default: true
  }
})
const emit = defineEmits(['instantiated', 'resized'])
// EChart 容器元素
const chartContainerRefs = ref(null)
// EChart 实例
let chart = null
// EChart 容器宽度 默认100%
const containerWidth = computed(() =>
  typeof props.width === 'number' ? `${props.width}px` : props.width
)
// EChart 容器高度 默认100%
const containerHeight = computed(() =>
  typeof props.height === 'number' ? `${props.height}px` : props.height
)
// 监听options, 重新绘制图表
watch(props.options, (newVal) => showChart(newVal))
// 监听地图geoJson, 重新绘制地图
watch(
  () => props.geoJson,
  () => initChart()
)
// EChart 实例化
const initChart = async () => {
  // 存在上个EChart实例 则先销毁
  chart && chart.dispose()
  // // 存在云词图表 则引用组件
  // props.wordCloud && (await import('echarts-wordcloud'))
  // 存在地图信息 则注册地图
  props.mapName && props.geoJson && echarts.registerMap(props.mapName, props.geoJson)
  // 存在第三方数据转换器, 则注册转换器 (星座图时可以用该功能绘制)
  props.transform && echarts.registerTransform(props.transform)
  // 创建一个EChart的实例
  const chartContainerEl = chartContainerRefs.value
  chart = echarts.init(chartContainerEl)
  // 开始绘制图表
  showChart()
  // 实例化后的钩子函数
  emit('instantiated', chart)
}
// 绘制图表
const showChart = (options = props.options) => {
  chart.setOption(options, props.notMerge)
}
// 监听窗口resize, 同时对chart进行resize
const resizeChart = () => {
  chart && chart.resize()
  emit('resized', chart)
}
function initResizeObserver() {
  const resizeObserver = new ResizeObserver((entries) => {
    for (const entry of entries) {
      if (entry.target.className === 'chartContainer') {
        resizeChart()
      }
    }
  })
  resizeObserver.observe(chartContainerRefs.value)
}
onMounted(() => {
  setTimeout(initChart)
  initResizeObserver()
})
</script>
